package com.zeus.web.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期时间工具类
 * 〈功能详细描述〉
 *
 * @author follow
 * @version 版本号, 18/4/14
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class DateUtils {

    private static final Logger logger = LoggerFactory.getLogger(DateUtils.class);

    public static final String CHINESE_DATE_FORMAT_YEAR_DAY = "yyyy-MM";
    public static final String CHINESE_DATE_FORMAT_DAY = "yyyyMMdd";
    public static final String CHINESE_DATE_FORMAT_SLASH = "yyyy/MM/dd";
    public static final String CHINESE_DATE_FORMAT_LINE = "yyyy-MM-dd";
    public static final String CHINESE_DATETIME_FORMAT_MINUTE = "yyyy-MM-dd HH:mm";
    public static final String CHINESE_DATETIME_FORMAT_LINE = "yyyy-MM-dd HH:mm:ss";
    public static final String CHINESE_DATETIME_FORMAT_SLASH = "yyyy/MM/dd HH:mm:ss";
    public static final long DAY_LONG = 60 * 60 * 24l;

    @SuppressWarnings("unused")
	private static final String[] SUPPORT_ALL_FORMATS = new String[]
            {
    				CHINESE_DATE_FORMAT_YEAR_DAY,CHINESE_DATE_FORMAT_DAY, CHINESE_DATE_FORMAT_SLASH, CHINESE_DATE_FORMAT_LINE,
                    CHINESE_DATETIME_FORMAT_MINUTE, CHINESE_DATETIME_FORMAT_LINE, CHINESE_DATETIME_FORMAT_SLASH
            };

    private static final String DEFAULT_DATE_FORMAT = CHINESE_DATETIME_FORMAT_LINE;
    private static final SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT);

    /**
     * 验证字符串是否日期
     *
     * @param str
     * @param pattern
     * @return
     */
    public static boolean isValidDate(String str, String pattern) {
        try {
            SimpleDateFormat format = new SimpleDateFormat(pattern);
            //设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            logger.warn(e.getMessage(), e);
            return false;
        }
        return true;
    }

    /**
     * 获取当前时间的 unix_timestamp
     *
     * @return
     */
    public static Integer getCurrentIntegerTime() {
        return getCurrentLongTime().intValue();
    }

    /**
     * 获取当前时间的 unix_timestamp
     *
     * @return
     */
    public static Long getCurrentLongTime() {
        return parse(new Date());
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date getCurrentDateTime() {
        return new Date();
    }

    public static Long parse(Date date) {
        return date.getTime() / 1000;
    }

    public static String format(Date date) {
        return format(date, DEFAULT_DATE_FORMAT);
    }

    public static String format(String pattern) {
        return format(new Date(), pattern);
    }
    
	public static String longToString(long time, String formatType)
			throws ParseException {
		if (String.valueOf(time).length() == 10) {
			time = time * 1000;
		}
		Date dateOld = new Date(time);
		String sDateTime = format(dateOld, formatType);
		return sDateTime;
	}

	public static Date longToDate(long time, String formatType)
			throws ParseException {
		if (String.valueOf(time).length() == 10) {
			time = time * 1000;
		}
		Date dateOld = new Date(time * 1000);
		String sDateTime = format(dateOld, formatType);
		Date date = parse(sDateTime, formatType);
		return date;
	}
    @Deprecated
    public static Date parse(String dateString, String pattern) {
        try {
            format.applyPattern(pattern);
            return format.parse(dateString);
        } catch (Exception e) {
            throw new RuntimeException("parse String[" + dateString + "] to Date faulure with pattern[" + pattern + "].");
        }
    }

    /**
     * 格式化日期
     *
     * @param date
     * @param pattern
     * @return
     */
    public synchronized static String format(Date date, String pattern) {
        format.applyPattern(pattern);
        return format.format(date);
    }

    /**
     * 根据当前日期获取最近7天的第一天
     *
     * @return
     */
    public static String getBeforeWeekStartStr() {
        format.applyPattern(CHINESE_DATE_FORMAT_LINE);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -7);
        return format.format(calendar.getTime()) + " 00:00:00";
    }

    public static Integer getBeforeWeekStartInt() {
        return parse(parse(getBeforeWeekStartStr(), CHINESE_DATETIME_FORMAT_LINE)).intValue();
    }

    /**
     * 根据当前日期获取最近一个月的第一天
     *
     * @return
     */
    public static String getBeforeMonthStartStr() {
        format.applyPattern(CHINESE_DATE_FORMAT_LINE);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        return format.format(calendar.getTime()) + " 00:00:00";
    }

    public static Integer getBeforeMonthStartInt() {
        return parse(parse(getBeforeMonthStartStr(), CHINESE_DATETIME_FORMAT_LINE)).intValue();
    }

    /**
     * 获取当前日期，yyyy-MM-dd HH:mm:ss 格式
     *
     * @return
     */
    public static String getTodayEndStr() {
        return format(new Date(), CHINESE_DATE_FORMAT_LINE) + " 23:59:59";
    }

    public static Integer getTodayEndInt() {
        return parse(parse(getTodayEndStr(), CHINESE_DATETIME_FORMAT_LINE)).intValue();
    }

    /**
     * 获取今日 18时00分00秒 的 unix_timestamp
     *
     * @return
     */
    public static Integer getTodayBefore18() {
        String todayBefore18Str = format(CHINESE_DATE_FORMAT_LINE) + " 18:00:00";
        Long todayBefore18 = parse(parse(todayBefore18Str, DEFAULT_DATE_FORMAT));

        return todayBefore18.intValue();
    }

    /**
     * 获取昨日 18时00分00秒 的 unix_timestamp
     *
     * @return
     */
    public static Integer getYesterdayBefore18() {
        return getTodayBefore18() - 1 * 24 * 60 * 60;
    }

    /**
     * 获取当前日期的年
     *
     * @return
     */
    public static Integer getCurrentYear() {
        return Calendar.getInstance().get(Calendar.YEAR);
    }

    /**
     * 获取当前日期的月
     *
     * @return
     */
    public static Integer getCurrentMonth() {
        return Calendar.getInstance().get(Calendar.MONTH) + 1;
    }

    /**
     * 获取上月今天的23点59分59秒的日期字符串
     * 修改：时间改为4小时之前的
     *
     * @return
     */
    public static String getTodayOfLastMonthYmdhmsStr() {
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(new Date());
        rightNow.add(Calendar.HOUR_OF_DAY, -4);

        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(rightNow.getTime());
    }

    /**
     * 获取当前日期， xxxx年xx月xx日 格式
     */
    public static String getCurrentDateStr() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.YEAR) + "年" + (calendar.get(Calendar.MONTH) + 1) + "月" + calendar.get(Calendar.DAY_OF_MONTH) + "日";
    }

    /**
     * yyyy-MM-dd 类型的日期 月份相加相减 正整数相加 负整数相减
     *
     * @param dateStr
     * @param month
     * @return
     */
    public static String getDateSub(String dateStr, int month) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(parse(dateStr, CHINESE_DATE_FORMAT_LINE));
        cal.add(Calendar.MONTH, month);

        return format(cal.getTime(), CHINESE_DATE_FORMAT_LINE);
    }

    /**
     * 获取当前时间的 yyyy-MM-dd HH:mm:ss 字符串格式
     *
     * @return
     */
    public static String getCurrentFormatYmdHmsForDate() {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    }

    /**
     * 获取当前时间的 yyyy-MM-dd HH:mm:ss 字符串格式
     *
     * @return
     */
    public static String getCurrentFormatYmd() {
        return new SimpleDateFormat("yyyy-MM-dd").format(new Date());
    }

	/**
	 * 获取两个日期相差月份
	 * 
	 * @param date1
	 *            yyyy-MM-dd格式日期
	 * @param date2
	 *            yyyy-MM-dd格式日期
	 * @return int
	 */
	public static int getMonthSpace(String date1, String date2) {
		SimpleDateFormat sdf = new SimpleDateFormat(CHINESE_DATE_FORMAT_LINE);
		String str1 = date1;
		String str2 = date2;
		Calendar bef = Calendar.getInstance();
		Calendar aft = Calendar.getInstance();
		try {
			bef.setTime(sdf.parse(str1));
			aft.setTime(sdf.parse(str2));
		} catch (ParseException e) {
			throw new RuntimeException("获取" + date1 + "与" + date2 + "日期间月份差数异常");
		}
		int result = aft.get(Calendar.MONTH) - bef.get(Calendar.MONTH);
		int month = (aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR)) * 12;
		return Math.abs(month + result);
	}
	
	/**
	 * 日期增加月份数
	 * 
	 * @param datetime
	 *            yyyy-MM-dd格式日期
	 * @return String
	 */
	public static String addMonth(String datetime, Integer num, String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		Date date = null;
		try {
			date = sdf.parse(datetime);
		} catch (ParseException e) {
			throw new RuntimeException(datetime + "日期增加月份数异常");
		}
		Calendar cl = Calendar.getInstance();
		cl.setTime(date);
		cl.add(Calendar.MONTH, num);
		date = cl.getTime();
		return sdf.format(date);
	}

    /**
     * 日期增加月份数
     *
     * @param datetime
     *            yyyy-MM-dd格式日期
     * @return String
     */
    public static Integer subtractionMonth(Integer datetime, Integer num) {
        Date date = new Date((long)datetime*1000);

        Calendar cl = Calendar.getInstance();
        cl.setTime(date);
        cl.add(Calendar.MONTH, num);
        cl.set(Calendar.DAY_OF_MONTH, cl.getActualMaximum(Calendar.DAY_OF_MONTH));
        return (parse(cl.getTime())).intValue();
    }

    /**
     * 获取某天的开始时间
     * @return
     */
    public static Integer getDayFirstTime(int num){
        Calendar calendar = Calendar.getInstance();
        calendar.add(calendar.DATE, num);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return ((Long)(calendar.getTimeInMillis()/1000)).intValue();
    }
    /**
     * 获取某天的结束时间
     * @return
     */
    public static Integer getDayEndTime(int num){
        Calendar calendar = Calendar.getInstance();
        calendar.add(calendar.DATE, num);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return ((Long)(calendar.getTimeInMillis()/1000)).intValue();
    }

    /**
     * 获取增加指定月份数后的月份的结束时间
     *
     * @param date 初始时间
     * @param addMonth 增加的月份数
     * @return 增加后的时间
     */
    public static Date getEndDateByAddMonth(Date date, Integer addMonth) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH);
        calendar.set(Calendar.MONTH, month + addMonth);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

    public static Date getFirstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);

        return calendar.getTime();
    }
    
    public static String formatDateTime(long timeMillis) {
		long day = timeMillis / 86400000L;
		long hour = timeMillis / 3600000L - day * 24L;
		long min = timeMillis / 60000L - day * 24L * 60L - hour * 60L;
		long s = timeMillis / 1000L - day * 24L * 60L * 60L - hour * 60L * 60L - min * 60L;
		return (day > 0L ? day + "," : "") + String.format("%02d", new Object[] { Long.valueOf(hour) }) + ":"
				+ String.format("%02d", new Object[] { Long.valueOf(min) }) + ":"
				+ String.format("%02d", new Object[] { Long.valueOf(s) });
	}
}
